package com.xiaoshuidi.cloud.module.rooms.mq.listener;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.module.member.api.user.MemberUserApi;
import com.xiaoshuidi.cloud.module.member.api.user.dto.MemberUserReqDTO;
import com.xiaoshuidi.cloud.module.member.api.user.dto.MemberUserRespDTO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.reservation.vo.ReserveTemplateExportVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomel.vo.RoomelUpdateReqVO;
import com.xiaoshuidi.cloud.module.rooms.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.rooms.enums.RentStatusEnum;
import com.xiaoshuidi.cloud.module.rooms.enums.RoomHouseReservePaymentStatus;
import com.xiaoshuidi.cloud.module.rooms.enums.RoomHouseReserveStatus;
import com.xiaoshuidi.cloud.module.rooms.framework.utils.CodeUtil;
import com.xiaoshuidi.cloud.module.rooms.job.delayjob.DelayJobService;
import com.xiaoshuidi.cloud.module.rooms.mq.producer.RoomEsProducer;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouse;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouseReserve;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomStateRecord;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomHouseRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomHouseReserveRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomStateRecordRepository;
import com.xiaoshuidi.cloud.module.rooms.valid.ExcelInValid;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static com.xiaoshuidi.cloud.module.rooms.enums.DelayJobType.DelayJobTypeEnum.DEPOSIT_PAYMENT_TERM;
import static com.xiaoshuidi.cloud.module.rooms.enums.DelayJobType.DelayJobTypeEnum.EXPIRATION_DATE;

@Slf4j
@Component
public class ReadingRoomReserveImportListener extends AnalysisEventListener<ReserveTemplateExportVO> {
    private final static String RESERVE_BILL_NO_PREFIX = "ZKDJZD";
    private final static String PAY_METHOD = "线下支付";
    private final List<ReserveTemplateExportVO> dataList= new ArrayList<>();
    private final RoomHouseReserveRepository roomHouseReserveRepository;
    private final RoomHouseRepository roomHouseRepository;
    private final RoomStateRecordRepository roomStateRecordRepository;
    private final MemberUserApi customerUserApi;
    private final RoomEsProducer roomEsProducer;
    private final CodeUtil codeUtil;
    private final DelayJobService delayJobService;



    @Override
    public void invoke(ReserveTemplateExportVO reserveTemplateExportVO, AnalysisContext analysisContext) {
        ExcelInValid.valid(reserveTemplateExportVO);
        // 将读取到的数据添加到集合中
        dataList.add(reserveTemplateExportVO);

    }

    @Override
    @Transactional(rollbackFor = {Exception.class},propagation = Propagation.REQUIRES_NEW)
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (CollectionUtil.isNotEmpty(dataList)) {
            for (ReserveTemplateExportVO reserveTemplateExportVO : dataList) {
                String roomHouseName = reserveTemplateExportVO.getRoomHouseName();
                Long roomHouseID = Long.parseLong(reserveTemplateExportVO.getRoomHouseID());
                //校验房源是否是空置状态
                RoomHouse house = roomHouseRepository.getByRoomId(roomHouseID);
                Assert.isTrue(ObjectUtil.isNotEmpty(house), roomHouseName+"房源信息不存在");
                if (house.getIsLock()) {
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), roomHouseName+"该房源已锁定,不可预定");
                }
                List<RoomStateRecord> stateRecordList = roomStateRecordRepository.listByRoomIdAndIsCurrentState(roomHouseID);
                Optional<RoomStateRecord> emptyStateRecord = stateRecordList.stream().filter(s -> RentStatusEnum.EMPTY.getValue().equals(s.getState())).findFirst();
                Optional<RoomStateRecord> stayingInStateRecord = stateRecordList.stream().filter(s -> RentStatusEnum.STAYINGIN.getValue().equals(s.getState())).findFirst();
                if (!emptyStateRecord.isPresent()) {
                    if (stayingInStateRecord.isPresent()) {
                    } else {
                        throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),roomHouseName+ "该房源不可预定");
                    }
                }
                //创建预定人信息
                String booker = reserveTemplateExportVO.getTenantName();
                String bookerPhone = reserveTemplateExportVO.getPhoneNum();
                String cardNo = reserveTemplateExportVO.getCardNo();
                MemberUserReqDTO userDto = new MemberUserReqDTO();
                userDto.setMobile(bookerPhone);
                userDto.setCardNo(cardNo);
                userDto.setName(booker);
                CommonResult<MemberUserRespDTO> userResult = customerUserApi.getUserInfo(userDto);
                if (!userResult.isSuccess()) {
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定人信息创建失败");
                }
                Long bookerId = userResult.getData().getId();

                RoomHouseReserve roomHouseReserve =new RoomHouseReserve();
                roomHouseReserve.setRoomHouseId(roomHouseID);
                roomHouseReserve.setBooker(booker);
                roomHouseReserve.setCustomType("1");
                roomHouseReserve.setBookerPhone(bookerPhone);
                String billAmount = reserveTemplateExportVO.getBillAmount();
                BigDecimal amount;
                try {
                     amount = new BigDecimal(billAmount);
                } catch (Exception e) {
                    throw new ServiceException(ErrorCodeConstants.FORMAT_ERROR.getCode(),"请输入正确的账单金额");
                }
                roomHouseReserve.setDeposit(amount);
                roomHouseReserve.setDepositPaymentTerm(reserveTemplateExportVO.getPaymentTerm());
                roomHouseReserve.setCardType("1");
                roomHouseReserve.setCardNo(cardNo);
                roomHouseReserve.setStatus(RoomHouseReserveStatus.TO_BE_PAID.getCode());
                roomHouseReserve.setPaymentStatus(RoomHouseReservePaymentStatus.UNTREATED.getCode());
                roomHouseReserve.setBookerId(bookerId);
                roomHouseReserve.setDeptId(house.getDeptId());
                roomHouseReserve.setCheckInDate(reserveTemplateExportVO.getCheckInDate());
                roomHouseReserve.setCheckOutDate(reserveTemplateExportVO.getCheckOutDate());
                roomHouseReserve.setExpirationDate(reserveTemplateExportVO.getExpirationDate());
                roomHouseReserve.setBillNo(codeUtil.nextCode(RESERVE_BILL_NO_PREFIX, 4));
                if(!reserveTemplateExportVO.getBillingStatus().equals(RoomHouseReservePaymentStatus.PROCESSED.getName())){
                roomHouseReserveRepository.save(roomHouseReserve);
                // 创建延迟任务, 处理待支付取消和已预定取消
                long depositPaymentTermMinutes = LocalDateTimeUtil.between(LocalDateTime.now(), roomHouseReserve.getDepositPaymentTerm()).toMinutes() + 1;
                long expirationDateMinutes = LocalDateTimeUtil.between(LocalDateTime.now(), roomHouseReserve.getExpirationDate()).toMinutes() + 1;
                delayJobService.addDelayJob(DEPOSIT_PAYMENT_TERM, roomHouseReserve.getId(), depositPaymentTermMinutes, TimeUnit.MINUTES);
                delayJobService.addDelayJob(EXPIRATION_DATE, roomHouseReserve.getId(), expirationDateMinutes, TimeUnit.MINUTES);
                log.info("房间预定ID:{}加入延迟队列", roomHouseReserve.getId());
                // 创建待支付账单 - 0530确认不创建账单信息

                //锁定当前房源，不可出租
                RoomHouse roomHouse = new RoomHouse();
                roomHouse.setIsLock(Boolean.TRUE);
                roomHouse.setId(roomHouseID);
                roomHouseRepository.updateById(roomHouse);
                //推送房源锁定状态到ES
                RoomelUpdateReqVO roomelUpdateReqVO = new RoomelUpdateReqVO();
                roomelUpdateReqVO.setIsLock(Boolean.TRUE);
                roomelUpdateReqVO.setId(roomHouseID);
                roomEsProducer.updateRoomEl(roomelUpdateReqVO);
                }else {
                    log.info("预定收款成功");
                    RoomHouse roomHouse = roomHouseRepository.getById(roomHouseID);
                    //支付成功 解锁房源; 如果房源为空置状态, 则更新当前状态为已预定; 如果房源当前房态为入住中, 则新增已预定房态;
                    roomHouse.setIsLock(Boolean.FALSE);
                    roomHouseReserve.setStatus(RoomHouseReserveStatus.RESERVED.getCode());
                    roomHouseReserve.setPaymentTime(reserveTemplateExportVO.getPaymentTime() == null ? LocalDateTime.now() : reserveTemplateExportVO.getPaymentTime());
//                reserve.setPaymentId(paymentId);
                    roomHouseReserve.setPaymentStatus(RoomHouseReservePaymentStatus.PROCESSED.getCode());
                    RoomStateRecord currentState = null;
                    try {
                        currentState = roomStateRecordRepository.getByRoomIdAndIsCurrentState(roomHouseID);
                    } catch (TooManyResultsException e) {
                        throw new RuntimeException("处理数据时发生错误", e);
                    }
                    RoomStateRecord stateRecord = new RoomStateRecord();
                    stateRecord.setRoomId(roomHouseID)
                            .setState(RentStatusEnum.SCHEDULED.getValue())
                            .setBeforeState(currentState.getState())
                            .setIsCurrentState(Boolean.TRUE);
                    log.info("预定支付成功-推送ES");
                    //推送ES状态
                    RoomelUpdateReqVO esVo = new RoomelUpdateReqVO();
                    esVo.setId(roomHouseID)
                            .setIsScheduled(Boolean.TRUE)
                            .setIsLock(Boolean.FALSE);
                    if (StrUtil.equals(RentStatusEnum.EMPTY.getValue(), currentState.getState())) {
                        currentState.setIsCurrentState(false);
                        roomStateRecordRepository.updateById(currentState);
                        esVo.setHouseState(RentStatusEnum.SCHEDULED.getValue());
                    }
                    roomHouseReserveRepository.save(roomHouseReserve);
                    roomStateRecordRepository.save(stateRecord);
                    roomHouseRepository.updateById(roomHouse);
                    roomEsProducer.updateRoomEl(esVo);
                }
            }
        }



    }

    public ReadingRoomReserveImportListener(RoomHouseRepository roomHouseRepository, MemberUserApi customerUserApi,RoomEsProducer roomEsProducer,RoomStateRecordRepository roomStateRecordRepository,RoomHouseReserveRepository roomHouseReserveRepository,CodeUtil codeUtil,DelayJobService delayJobService){
        this.roomHouseRepository=roomHouseRepository;
        this.customerUserApi=customerUserApi;
        this.roomEsProducer =roomEsProducer;
        this.roomStateRecordRepository =roomStateRecordRepository;
        this.roomHouseReserveRepository = roomHouseReserveRepository;
        this.codeUtil = codeUtil;
        this.delayJobService = delayJobService;
    }
}
